/**
Company: Sarkar software technologys
WebSite: http://www.sarkar.cn
Author: yeganaaa
Date : 10/31/17
Time: 6:03 PM
 */

package Cn.Sarkar.SimplePipeLineServer.Core.Utils

class KeyValuePair<K, V>(val key: K, vararg values: V) {
    val values: ArrayList<V> = ArrayList()

    init {
        this.values.addAll(values)
    }

    operator fun get(index: Int) = values[index]
    operator fun set(index: Int, value: V) {
        values[index] = value
    }

    var first: V
        get() {
            return values.first()
        }
        set(value) {
            values[0] = value
        }
    var last: V
        get() {
            return values.last()
        }
        set(value) {
            values[values.lastIndex] = value
        }

    override fun toString(): String {
        var retv = "Key: $key "
        var index = 0
        values.forEach {
            retv += " value-${index++}: $it"
        }
        return retv
    }
}

class ValuesMap<K, V> {
    private val maps = HashMap<K, KeyValuePair<K, V>>()

    fun getFirst(key: K) = maps[key]?.values?.first()
    fun getLast(key: K) = maps[key]?.values?.last()
    operator fun get(key: K) = maps[key]
    operator fun get(key: K, index: Int) = maps[key]?.get(index)
    fun getAll(key: K) = maps[key]?.values?.toList()

    fun getAllKeys() = maps.keys

    fun setFirst(key: K, value: V){
        maps[key]?.first = value
    }

    fun setLast(key: K, value: V){
        maps[key]?.last = value
    }
    operator fun set(key: K, index: Int, value: V)
    {
        maps[key]?.set(index, value)
    }
    fun add(keyAndValues: KeyValuePair<K, V>){
        if (!(keyAndValues.key in maps.keys)){
            maps.put(keyAndValues.key, KeyValuePair(keyAndValues.key))
        }
        maps[keyAndValues.key]?.values?.addAll(keyAndValues.values)
    }
    fun addAll(vararg keyAndValues: KeyValuePair<K, V>)
    {
        keyAndValues.forEach(this::add)
    }
    fun remove(key: K){
        maps.remove(key)
    }
    fun remove(key: K, index: Int){
        maps[key]?.values?.removeAt(index)
    }
    fun removeAll(){
        maps.forEach { k, v ->
            maps.remove(k)
        }
    }
    fun forEach(action: (KeyValuePair<K, V>) -> Unit){
        maps.forEach { k, v ->
            action(v)
        }
    }

    override fun toString(): String {
        var retv = ""
        maps.forEach {
            retv += it.value.toString()
        }
        return retv
    }
}

fun <K, V>valuesMapOf(vararg keyValuePairs: KeyValuePair<K, V>) : ValuesMap<K, V> {
    val result = ValuesMap<K, V>()
    result.addAll(*keyValuePairs)
    return result
}

